package team02.server;

import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONObject;

import permute.Permute;
import team02.client.TestService;
import team02.client.core.test.Examinee;
import team02.client.core.test.Test;
import team02.client.core.test.question.Question;
import team02.client.core.test.question.QuestionAN;
import team02.client.core.test.question.QuestionS;
import team02.client.util.Pair;
import team02.server.bean.ExamineeBean;
import team02.server.bean.QuestionBean;
import team02.server.bean.TestBean;
import team02.server.bean.UserBean;
import team02.server.core.parser.CSVParser;
import team02.server.exception.ParserException;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class TestServiceImpl extends RemoteServiceServlet implements TestService {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6084400957184711284L;
	private int testMakerId = 0;
	private int examineeId = 0;
	private HttpServletRequest request;
	private HttpServletResponse response;

	@Override
	public Test getTest(int userId, long time) {
		Test test = new Test();
		test.setCreatedBy(userId);
		test.setCreatedTime(time);

		TestBean bean = new TestBean();
		bean.setTest(test);
		try {
			bean.load();
			
			ArrayList<Examinee> examineeList = test.getExamineeList();
			for (Examinee examinee : examineeList) {
				if(examinee.getId() == this.examineeId && examinee.isSubmitted()) {//thằng làm bài thi này đã nộp bài
					//do something
				}
			}
			
			return test;
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		}
	}

	@Override
	public void submitTest(Test test) {
		if (this.examineeId != 0) {
			test.setExamineeId(this.examineeId);
			score(test);
			try {
				storeAnswer(test);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} else { //simulation

		}
	}

	private void storeAnswer(Test test) throws SQLException {
		QuestionBean questionBean = new QuestionBean();
		for (Question question : test) {
			
			questionBean.setQuestion(question);
			questionBean.insertAnswer(test.getExamineeId());
		}
		
		TestBean testBean = new TestBean();
		testBean.setTest(test);
		testBean.storeScore();
	}

	/**
	 * 採点
	 * 
	 * @param test
	 */
	private void score(Test test) {
		int totalScore = 0;
		for (Question question : test) {
			ArrayList<QuestionAN> answerList = question.getAnswerList();
			//			boolean scoreDone = false;
			int questionScore = 0;
			if (question.getType().equals(Question.TYPE_SELECTION)) {//QS
				ArrayList<Integer> examineeSelections = question.getExamineeSelection();
				for (QuestionAN questionAN : answerList) {
					String anType = questionAN.getType();
					List<QuestionS> rightSelections = questionAN.getSelectionList();
					if (anType.equals(Question.QUESTION_ANSWER_TYPE_KS)) {
						if (examineeSelections.size() != 1) continue;
						if (examineeSelections.get(0) == rightSelections.get(0).getSelectionNumber()) {
							questionScore += questionAN.getScoreInt();
							//							scoreDone = true;
							break;
						}
					} else if (anType.equals(Question.QUESTION_ANSWER_TYPE_KSA)) {
						if (examineeSelections.size() != rightSelections.size()) continue;
						ArrayList<Integer> rightSelectionNumber = new ArrayList<Integer>();
						for (QuestionS questionS : rightSelections) {
							rightSelectionNumber.add(questionS.getSelectionNumber());
						}
						if (rightSelectionNumber.containsAll(examineeSelections)) {
							questionScore += questionAN.getScoreInt();
							break;
						}

					} else if (anType.equals(Question.QUESTION_ANSWER_TYPE_KSO)) {
						if (examineeSelections.size() != 1) continue;
						for (QuestionS questionS : rightSelections) {
							if (questionS.getSelectionNumber() == examineeSelections.get(0)) {
								questionScore += questionAN.getScoreInt();
								break;
							}
						}
						continue;
					}
				}
			} else { //QW
				for (QuestionAN questionAN : answerList) {
					ArrayList<String> examineeRealWrites = question.getRealExamineeWrite();
					
//					if(question.getQuestionANC().contains(questionAN)) {
						for (String write : examineeRealWrites) {
//							System.out.println("REAL" + write);
							if(isMatch(questionAN, write)) {
								questionScore += questionAN.getScoreInt();
								break;
							}
						}
//					}
//					else {
//						if(isMatch(questionAN, question.getExamineeWrite().get(questionAN.getAnswerNumber() - 1)) {
//							questionScore += questionAN.getScoreInt();
//							continue;
//						}
//					}

					
				}
			}
			if(test.getType().equals(Test.TYPE_FIX) && Question.QUESTION_LIMIT.equals(question.getTimeStyle())) {
				Pair limitPoints = question.getLimitPoints();
				long usedTime = question.getUsedTime();
				if(usedTime > limitPoints.first) {
					questionScore  -= Math.round(((double) questionScore)/(limitPoints.second - limitPoints.first) * (usedTime - limitPoints.first));
				}
			}
			question.setScore(questionScore);
			System.out.println(new Date() + "QUESTION " + question.getQuestionNo() + " SCORE " + questionScore);
			totalScore += question.getScore();
		}
		test.setScore(totalScore);

	}

//	@Override
//	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//		ExamineeBean examineeBean = (ExamineeBean) req.getSession().getAttribute("examineeBean");
//		if (examineeBean == null) {//simulation
//			UserBean testMaker = (UserBean) req.getSession().getAttribute("userBean");
//			this.testMakerId = testMaker.getUserId();
//		} else {
//			this.examineeId = examineeBean.getId();
//		}
//		super.doGet(req, resp);
//	}

	private boolean isMatch(QuestionAN questionAN, String write) {
	
		
		String anType = questionAN.getType();
//		System.out.println(anType);
		List<String> rightWrites = questionAN.getWriteList();
		if (anType .equals(Question.QUESTION_ANSWER_TYPE_KWA)
				|| anType.equals(Question.QUESTION_ANSWER_TYPE_KW)) {
			if(write.equals(rightWrites.get(0))) return true;
		} else if (anType.equals(Question.QUESTION_ANSWER_TYPE_KWAA)) {
			return false;//chịu, không biết chấm kiểu gì
		} else if (anType.equals(Question.QUESTION_ANSWER_TYPE_KWAO)) {
			for (String rightAnswer : rightWrites) {
				if(rightAnswer.equals(write)) return true;
			}
		} else if (anType.equals(Question.QUESTION_ANSWER_TYPE_KWP)) {
			if(write.contains(rightWrites.get(0))) return true;
		} else if (anType.equals(Question.QUESTION_ANSWER_TYPE_KWPA)) {
			return false;//chịu, cũng ko chấm nổi
//			if (examineeRealWrites.size() != rightWrites.size()) continue;
//			ArrayList<QuestionAN> questionANC = question.getQuestionANC();
//			if (questionANC.contains(questionAN)) {
//				Integer[] index = new Integer[examineeRealWrites.size()];
//				for (int i = 0; i < index.length; i++) {
//					index[i] = i;
//				}
//				for (Iterator i = new Permute(index); i.hasNext();) {
//					final Integer[] next = (Integer[]) i.next();//permutations
//					//check
//					boolean match = true;
//					for (int k = 0; k < index.length; k++) {
//						if (!examineeRealWrites.get(next[k]).contains(rightWrites.get(k))) {
//							match = false;
//							break;
//						}
//					}
//					if (match) { //KWPA match
//						questionScore += questionAN.getScoreInt();
//						break;
//					}
//				}
//			} else {
//				boolean match = true;
//				for (int k = 0; k < examineeRealWrites.size(); k++) {
//					if (!examineeRealWrites.get(k).contains(rightWrites.get(k))) {
//						match = false;
//						break;
//					}
//				}
//				if (match) {
//					questionScore += questionAN.getScoreInt();
//					break;
//				}
//			}
		} else if (anType.equals(Question.QUESTION_ANSWER_TYPE_KWPO)) {
			for (String rightAnswer : rightWrites) {
				if(write.contains(rightAnswer)) return true;
			}
		} else if (anType.equals(Question.QUESTION_EXAMINER_INSERT_TYPE_MARK)) {
			
		}
		return false;
	}

	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.request = request;
		this.response = response;
		ExamineeBean examineeBean = (ExamineeBean) request.getSession().getAttribute("examineeBean");
		if (examineeBean == null) {//simulation
			UserBean testMaker = (UserBean) request.getSession().getAttribute("userBean");
			if(testMaker != null) {
			this.testMakerId = testMaker.getUserId();
			}
		} else {
			this.examineeId = examineeBean.getId();
		}
		super.service(request, response);
	}

	@Override
	public String viewScore(int examineeId) {
		ExamineeBean bean = new ExamineeBean();
		bean.setId(examineeId);
		try {
			if(bean.load() == 0) {
				JSONObject score = new JSONObject();
				score.append("score1", bean.getExaminee().getScore());
				
				if(bean.getExaminee().isMarked()) {
					score.append("score2", bean.getExaminee().getScore2());
				}
				return score.toString();
			}
			return null;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
}
